import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.ImageIcon;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.awt.Cursor;
import javax.swing.border.SoftBevelBorder;

// Important : All toolbar handler actions are called from
// their corresponding code in the menu handler

/**
 * ToolBarHandler handles ToolBar.
 *
 * @version 1.0
 * @author P.Jaya Krishna
 */
class ToolBarHandler implements ActionListener
{
	// refers to the frame whose toolbar is being handled
	private GFrame gFrame;
	// used to show File Save, Save As and Open dialogs
	private JFileChooser fileChooser;
	// used to store the delay of the animator
	private int previousDelay;
	
	// the following are obtained from menu handler
	// tells whether the current file is saved before or not
	// "isFileSaved" is obtained from menu handler of the frame
	// refers to the currently used file
	// "currentFile" is obtained from menu handler of the frame
	
	/**
	 * Creates a ToolBarHandler to handler the toolbar of "gFrame".
	 */
	public ToolBarHandler(GFrame gFrame)
	{
		this.gFrame = gFrame;
		fileChooser = new JFileChooser(".");
		fileChooser.addChoosableFileFilter(new GRAFilter());
	}
	
	/**
	 * Checks which toolbar button is pressed and does required operation
	 */
	public void actionPerformed(ActionEvent ae)
	{
		// new
		if(ae.getSource().equals(gFrame.toolBar.TBNew))
		{
			boolean type = false;
			Object[] options = { "Undirected", "Directed", "Cancel"};
			
			int returnval = JOptionPane.showOptionDialog(gFrame, "What is the type of new graph to be created", "Graph Type", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
			
			if(returnval == -1 || returnval == 2)
				return;
			else if(returnval == 1)
					type = true;
			Graph newGraph = new Graph(type);
			gFrame.gPanel.setGraph(newGraph);
			gFrame.menuHandler.isFileSaved = false;
			gFrame.setTitle("GRASP - [File Not Saved]");
		}
		// open
		else if(ae.getSource().equals(gFrame.toolBar.TBOpen))
		{
			int returnVal = fileChooser.showOpenDialog(gFrame);
			
			if(returnVal == JFileChooser.APPROVE_OPTION)
			{
				try
				{
					if(fileChooser.getSelectedFile().exists())
						gFrame.menuHandler.currentFile = fileChooser.getSelectedFile();
					else
						gFrame.menuHandler.currentFile = new File(fileChooser.getSelectedFile().getPath().concat(".gra"));
					
					ObjectInputStream ois = new ObjectInputStream(new FileInputStream(gFrame.menuHandler.currentFile));
					gFrame.gPanel.setGraph((Graph)ois.readObject());
					gFrame.menuHandler.isFileSaved = true;
					gFrame.setTitle("GRASP - [" + gFrame.menuHandler.currentFile.getName() + "]");
				}
				catch(Exception e)
				{
					JOptionPane.showMessageDialog(gFrame, "File not Found or Invalid file format", "File cannot be opened", JOptionPane.ERROR_MESSAGE);
				}
			}
		}
		// save
		else if(ae.getSource().equals(gFrame.toolBar.TBSave))
		{
			// show Save dialog only if file is not yet saved
			if(gFrame.menuHandler.isFileSaved == false)
			{
				int returnVal = fileChooser.showSaveDialog(gFrame);
				
				if(returnVal == JFileChooser.APPROVE_OPTION)
				try
				{
					gFrame.menuHandler.currentFile = fileChooser.getSelectedFile();
					
					if (!gFrame.menuHandler.currentFile.getName().endsWith(".gra"))
						gFrame.menuHandler.currentFile = new File(gFrame.menuHandler.currentFile.getPath().concat(".gra"));
						
					ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(gFrame.menuHandler.currentFile));
					oos.writeObject(gFrame.gPanel.getGraph());
					gFrame.menuHandler.isFileSaved = true;
					gFrame.toolBar.TBUndo.setEnabled(false);
					gFrame.toolBar.TBRedo.setEnabled(false);
					gFrame.menuBar.menuEditUndo.setEnabled(false);
					gFrame.menuBar.menuEditRedo.setEnabled(false);
					gFrame.setTitle("GRASP - [" + gFrame.menuHandler.currentFile.getName() + "]");
				}
				catch(Exception e)
				{
					JOptionPane.showMessageDialog(gFrame, "Unable to save file", "Error", JOptionPane.ERROR_MESSAGE);
				}
			}
			// otherwise directly save the file without prompting for name
			else
			{
				try
				{
					ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(gFrame.menuHandler.currentFile));
					oos.writeObject(gFrame.gPanel.getGraph());
					gFrame.toolBar.TBUndo.setEnabled(false);
					gFrame.toolBar.TBRedo.setEnabled(false);
					gFrame.menuBar.menuEditUndo.setEnabled(false);
					gFrame.menuBar.menuEditRedo.setEnabled(false);
				}
				catch(Exception e)
				{
					JOptionPane.showMessageDialog(gFrame, "Unable to save file", "Error", JOptionPane.ERROR_MESSAGE);
				}
			}
		}
		// undo
		else if(ae.getSource().equals(gFrame.toolBar.TBUndo))
		{
			gFrame.gPanel.undo();
		}
		// redo
		else if(ae.getSource().equals(gFrame.toolBar.TBRedo))
		{
			gFrame.gPanel.redo();
		}
		// refresh
		else if(ae.getSource().equals(gFrame.toolBar.TBRefresh))
		{
			gFrame.gPanel.refresh();
			gFrame.helpPanel.setText("");
			gFrame.messagePanel.setText("");
			gFrame.statusBar.setMessage(GStatusBar.STATUS_ALGORITHM_EXE,"");
			gFrame.statusBar.setMessage(GStatusBar.STATUS_ALGORITHM_OUT,"");
		}
		// step by step graph operations
		else if(ae.getSource().equals(gFrame.toolBar.TBStepByStep))
		{
			if(!gFrame.toolBar.TBStepByStep.isSelected())
			{
				gFrame.toolBar.TBStepByStep.setBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED));
				gFrame.toolBar.TBStepByStep.setSelected(true);
				gFrame.menuBar.menuToolsShowStepByStep.setSelected(true);
				gFrame.menuBar.menuToolsAdjustSpeed.setEnabled(true);
				gFrame.gPanel.animationDelay = previousDelay;
			}
			else
			{
				gFrame.toolBar.TBStepByStep.setBorder(new SoftBevelBorder(2));
				gFrame.toolBar.TBStepByStep.setSelected(false);
				gFrame.menuBar.menuToolsShowStepByStep.setSelected(false);
				gFrame.menuBar.menuToolsAdjustSpeed.setEnabled(false);
				previousDelay = gFrame.gPanel.animationDelay;
				gFrame.gPanel.animationDelay = 0;
			}
		}
		else if(ae.getSource().equals(gFrame.toolBar.TBSelect))
		{
			if(!gFrame.toolBar.TBSelect.isSelected())
			{
				gFrame.toolBar.TBSelect.setSelected(true);
				gFrame.toolBar.TBVertex.setSelected(false);
				gFrame.toolBar.TBEdge.setSelected(false);
				gFrame.toolBar.TBSelect.setBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED));
				gFrame.toolBar.TBEdge.setBorder(new SoftBevelBorder(2));
				gFrame.toolBar.TBVertex.setBorder(new SoftBevelBorder(2));
				gFrame.gPanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
				gFrame.gPanel.setCurrentAction(GPanel.ACTION_SELECT);
				gFrame.menuBar.menuToolsOpSelection.setSelected(true);
			}
		}
		else if(ae.getSource().equals(gFrame.toolBar.TBVertex))
		{
			if(!gFrame.toolBar.TBVertex.isSelected())
			{
				gFrame.toolBar.TBSelect.setBorder(new SoftBevelBorder(2));
				gFrame.toolBar.TBVertex.setBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED));
				gFrame.toolBar.TBEdge.setBorder(new SoftBevelBorder(2));
				gFrame.gPanel.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
				gFrame.toolBar.TBVertex.setSelected(true);
				gFrame.toolBar.TBSelect.setSelected(false);
				gFrame.toolBar.TBEdge.setSelected(false);
				gFrame.gPanel.setCurrentAction(GPanel.ACTION_VERTEX);
				gFrame.menuBar.menuToolsOpVertex.setSelected(true);
			}
		}
		else if(ae.getSource().equals(gFrame.toolBar.TBEdge))
		{
			if(!gFrame.toolBar.TBEdge.isSelected())
			{
				gFrame.toolBar.TBSelect.setSelected(false);
				gFrame.toolBar.TBVertex.setSelected(false);
				gFrame.toolBar.TBEdge.setSelected(true);
				gFrame.toolBar.TBSelect.setBorder(new SoftBevelBorder(2));
				gFrame.toolBar.TBEdge.setBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED));
				gFrame.toolBar.TBVertex.setBorder(new SoftBevelBorder(2));
				gFrame.gPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
				gFrame.gPanel.setCurrentAction(GPanel.ACTION_EDGE);
				gFrame.menuBar.menuToolsOpEdge.setSelected(true);
			}
		}
		//show edge weights, default enabled
		else if(ae.getSource().equals(gFrame.toolBar.TBShowWeights))
		{
			if(!gFrame.toolBar.TBShowWeights.isSelected())
				gFrame.toolBar.TBShowWeights.setBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED));
			else
				gFrame.toolBar.TBShowWeights.setBorder(new SoftBevelBorder(2));
			
			gFrame.gPanel.setShowEdgeWeights(!gFrame.toolBar.TBShowWeights.isSelected());
			gFrame.toolBar.TBShowWeights.setSelected(!gFrame.toolBar.TBShowWeights.isSelected());
			gFrame.menuBar.menuToolsShowWeights.setSelected(gFrame.toolBar.TBShowWeights.isSelected());
		}
		else if(ae.getSource().equals(gFrame.toolBar.TBAdjMatrix))
		{
			new AdjMatrixDialog(gFrame);
		}
	}
}